﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Caching;
using System.Web;
using System.Xml.Serialization;

namespace blackhouse.Payments {

    /// <summary>
    /// Przechowywanie konfiguracji do obsługi serwisu PayU.pl
    /// </summary>
    [Serializable]
    public class PayUConfig {

        #region Properties

        public int PosID { get; set; }
        public string PosAuthKey { get; set; }
        public bool Testing { get; set; }
        public string KeyIn { get; set; }
        public string KeyOut { get; set; }
        public string ProcedureGetUrl { get; set; }
        public string Extension { get; set; }

        #endregion

        #region Constructors

        private PayUConfig() {
            this.PosID = -1;
            this.PosAuthKey = "type key";
            this.Testing = true;
            this.ProcedureGetUrl = "https://www.platnosci.pl/paygw/UTF/Payment/get";
        }

        #endregion

        #region Methods

        public IPaymentTransactionExtension GetExtension() {
            if (string.IsNullOrEmpty(this.Extension))
                return null;

            Type t = Type.GetType(this.Extension, false, true);
            if (t == null)
                return null;

            return Activator.CreateInstance(t) as IPaymentTransactionExtension;
        }

        public static PayUConfig Get() {
            string filePath;
            if (HttpContext.Current == null || HttpContext.Current.Server == null) {
                filePath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\payment.config";
            }
            else {
                DirectoryInfo di = new DirectoryInfo(HttpContext.Current.Server.MapPath("~/Payments"));
                if (!di.Exists)
                    di = new DirectoryInfo(HttpContext.Current.Server.MapPath("~"));
                filePath = di.FullName + "\\payment.config";
            }
            return Get(filePath);
        }

        public static PayUConfig Get(string file) {
            FileInfo f = new FileInfo(file);
            PayUConfig config;
            if (f.Exists) {
                config = TryGetFromCache(file);
                if (config != null) return config;
                config = GetFromFile(f);
                if (config == null) {
                    f.Delete();
                    config = new PayUConfig();
                    SaveToFile(config, f);
                }
            }
            else {
                config = new PayUConfig();
                SaveToFile(config, f);
            }
            SaveToCache(file, config);
            return config;
        }

        private static PayUConfig TryGetFromCache(string file) {
            if (MemoryCache.Default.Contains(file))
                return MemoryCache.Default[file] as PayUConfig;
            else return null;
        }

        private static void SaveToCache(string file, PayUConfig config) {
            CacheItem ci = new CacheItem(file, config);
            CacheItemPolicy cip = new CacheItemPolicy();
            cip.SlidingExpiration = TimeSpan.FromHours(100);
            List<string> filePath = new List<string>();
            filePath.Add(file);
            cip.ChangeMonitors.Add(new HostFileChangeMonitor(filePath));
            MemoryCache.Default.Set(ci, cip);
        }

        private static void SaveToFile(PayUConfig config, FileInfo f) {
            XmlSerializer serializer = new XmlSerializer(typeof(PayUConfig));
            using (FileStream fs = f.OpenWrite()) {
                serializer.Serialize(fs, config);
            }
        }

        private static PayUConfig GetFromFile(FileInfo file) {
            PayUConfig config = null;
            XmlSerializer serializer = new XmlSerializer(typeof(PayUConfig));
            try {
                using (FileStream fs = file.OpenRead()) {
                    config = serializer.Deserialize(fs) as PayUConfig;
                }
            }
            catch (Exception) {
                config = null;
            }
            return config;
        }

        #endregion

    }
}